package com.wayz.service;

import com.wayz.constants.CUserStatus;
import com.wayz.constants.PageVo;
import com.wayz.entity.dto.user.LoginDto;
import com.wayz.entity.dto.user.PageUserAdminDto;
import com.wayz.entity.dto.user.UserAdminDto;
import com.wayz.entity.pojo.user.DUserAdmin;
import com.wayz.entity.pojo.user.DUserAdminExt;
import com.wayz.entity.redis.role.RUserAdmin;
import com.wayz.entity.vo.user.UserAdminVo;
import com.wayz.exception.WayzException;
import com.wayz.mapper.DUserAdminDAO;
import com.wayz.redis.BeanIdKeyEnum;
import com.wayz.redis.RedisUtils;
import com.wayz.util.EncryptHelper;
import com.wayz.util.TimeHelper;
import com.wayz.util.VerifyCodeHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service(version = "1.0.0", protocol = "dubbo")
@RefreshScope
public class UserAdminServiceImpl implements UserAdminService {
    /** 标识相关 */
    /** 用户标记标识 */
    @Resource(name = "redisUtils")
    private RedisUtils redisUtils = null;

    /** DAO相关 */
    /** 用户DAO */
    @Resource(name = "dUserAdminDAO")
    private DUserAdminDAO dUserAdminDAO = null;

    /** 属性相关 */
    /** 令牌超时时间(秒) */
    @Value("${user.token.timeout}")
    private Long tokenTimeout = null;
    /** 验证码超时时间(分钟) */
    @Value("${common.system.authCodeTimeout}")
    private Long authCodeTimeout = null;

    /**
     * 获取我的用户
     *
     * @param myId 我的标识
     * @return 我的用户
     * @throws WayzException 云歌广告平台异常
     */
    @Override
    public UserAdminVo getMyUser(Long myId) throws WayzException {
        // 初始化
        UserAdminVo user = null;

        // 获取角色
        DUserAdminExt dUserExt = dUserAdminDAO.getExt(myId);

        // 数据转换
        if (dUserExt != null) {
            user = new UserAdminVo();

            // 获取广告计划类型
            Long roleId = dUserExt.getRoleId();
            user.setId(dUserExt.getId());
            user.setCompanyId(dUserExt.getCompanyId());
            user.setCompanyName(dUserExt.getCompanyName());
            user.setRoleId(roleId);
            user.setRoleName(dUserExt.getRoleName());
            user.setUsername(dUserExt.getUsername());
            user.setStatus(dUserExt.getStatus());
            user.setName(dUserExt.getName());
            user.setGender(dUserExt.getGender());
            user.setPhone(dUserExt.getPhone());
            user.setEmail(dUserExt.getEmail());
            user.setTitle(dUserExt.getTitle());
            user.setAvatar(dUserExt.getAvatar());
        }

        // 返回数据
        return user;
    }

    /**
     * 获取验证码
     *
     * @param sessionId 会话标识
     * @return 字节数组
     * @throws WayzException 健身馆异常
     */
    @Override
    public byte[] getAuthcode(String sessionId) throws WayzException {
        // 获取验证码
        String authCode = VerifyCodeHelper.getVerifyCode(4);

        // 获取验证图片
        byte[] bytes = VerifyCodeHelper.getVerifyImage(authCode);

        // 保存验证码
        // rSessionAuthCodeValue.set(sessionId, authCode, authCodeTimeout,
        // TimeUnit.MINUTES);
        redisUtils.set(BeanIdKeyEnum.AUTHCODE_ADMIN.getKey() + sessionId, authCode, authCodeTimeout, TimeUnit.MINUTES);

        // 返回验证图片
        return bytes;
    }

    /**
     * 登录
     * @return 登录令牌
     * @throws WayzException 云歌广告平台异常
     */
    @Override
    public String login(LoginDto loginDto)
            throws WayzException {
        // 检查用户
        DUserAdmin dUserAdmin = dUserAdminDAO.getByUsernameOrPhone(loginDto.getUsername());
        if (dUserAdmin == null) {
            throw new WayzException("用户不存在或密码错误");
        }
        if (dUserAdmin.getStatus() == null || dUserAdmin.getStatus().equals(CUserStatus.DISABLE.getValue())) {
            throw new WayzException("用户被禁用");
        }
        // 非第三方登录,需要校验图片验证码
        if (loginDto.getPassword() == null || !loginDto.getPassword().equalsIgnoreCase(dUserAdmin.getPassword())) {
            throw new WayzException("用户不存在或密码错误");
        }

        String authCodeRedis = redisUtils.get(BeanIdKeyEnum.AUTHCODE_ADMIN.getKey() + loginDto.getSessionId());
        if (authCodeRedis == null || !authCodeRedis.equals(loginDto.getAuthCode())) {
            throw new WayzException("图片验证码错误");
        }
        // 添加令牌
        String token = EncryptHelper.toMD5(loginDto.getUsername() + System.currentTimeMillis());
        redisUtils.set(BeanIdKeyEnum.LOGIN_TOKEN_ADMIN.getKey() + token, dUserAdmin.getId().toString(), tokenTimeout,
                TimeUnit.SECONDS);
        // 返回数据
        return token;
    }

    /**
     * 获取我的标识
     *
     * @param token 登录令牌
     * @return 我的标识
     * @throws WayzException 云歌广告平台异常
     */
    @Override
    public Long getMyId(String token) throws WayzException {
        // 初始化
        String myId = redisUtils.get(BeanIdKeyEnum.LOGIN_TOKEN_ADMIN.getKey() + token);
        // 重设超时
        if (StringUtils.isNotEmpty(myId)) {
            redisUtils.expire(BeanIdKeyEnum.LOGIN_TOKEN_ADMIN.getKey() + token, tokenTimeout, TimeUnit.SECONDS);
            // 返回数据
            return Long.parseLong(myId);
        }
        return null;
    }

    /**
     * 创建用户
     *
     * @param myId 我的标识
     * @param userAdminCreateVo
     * @return 用户标识
     * @throws WayzException 云歌广告平台异常
     */
    @Override
    public Long createUser(Long myId, UserAdminDto userAdminCreateVo) throws WayzException {
        // 写入mysql数据库user信息
        DUserAdmin dUserAdminCreate = this.insertUser(myId, userAdminCreateVo);

        // 写入redis用户信息
        cacheUser(dUserAdminCreate);

        // 返回标识
        return dUserAdminCreate.getId();
    }

    /**
     * 用户表写入数据
     *
     * @return
     */
    private DUserAdmin insertUser(Long myId, UserAdminDto userAdminCreateVo) throws WayzException {
        // 检查用户电话
        if (dUserAdminDAO.existsPhone(userAdminCreateVo.getPhone(), null)) {
            throw new WayzException("手机号已存在!");
        }
        if (dUserAdminDAO.existsUsername(userAdminCreateVo.getUsername())) {
            throw new WayzException("用户名已存在!");
        }
        // 创建用户
        Long userId = redisUtils.incrBy(BeanIdKeyEnum.USER_ADMIN.getKey(), RedisUtils.STEP_SIZE);
        DUserAdmin dUserAdminCreate = new DUserAdmin();
        BeanUtils.copyProperties(userAdminCreateVo, dUserAdminCreate);
        dUserAdminCreate.setCreatorId(myId);
        dUserAdminCreate.setStatus(CUserStatus.ENABLE.getValue());
        dUserAdminCreate.setIsDeleted(false);
        dUserAdminCreate.setId(userId);
        dUserAdminDAO.create(dUserAdminCreate);
        return dUserAdminCreate;
    }

    /**
     * 设置用户信息缓存
     *
     * @param dUserAdminCreate
     * @throws WayzException
     */
    private void cacheUser(DUserAdmin dUserAdminCreate) throws WayzException {
        // 缓存用户
        RUserAdmin rUserAdmin = new RUserAdmin();
        BeanUtils.copyProperties(dUserAdminCreate, rUserAdmin);
        String key = RUserAdmin.getKey(dUserAdminCreate.getId());
        redisUtils.hPutBeanAsHash(key, rUserAdmin);
    }

    /**
     * 查询用户
     * @return 用户分页
     * @throws WayzException 云歌广告平台异常
     */
    @Override
    public PageVo<UserAdminVo> queryUser(Long myId, PageUserAdminDto pageUserAdminDto) {
        // 初始化
        PageVo<UserAdminVo> userAdminPage = new PageVo<>();
        List<UserAdminVo> userList = new ArrayList<UserAdminVo>();
        // 查询数据
        // 查询数据: 用户总数
        Integer totalCount = dUserAdminDAO.countByCondition(pageUserAdminDto.getStatus(), pageUserAdminDto.getName());
        if (totalCount <= 0) {
            return userAdminPage;
        }
        // 查询数据: 用户列表
        List<DUserAdminExt> dUserExtList = dUserAdminDAO.queryExtByCondition(pageUserAdminDto.getStatus(),
                pageUserAdminDto.getName(), pageUserAdminDto.getStartIndex(), pageUserAdminDto.getPageSize());
        // 转化数据
        UserAdminVo user;
        if (dUserExtList != null) {
            for (DUserAdminExt dUserExt : dUserExtList) {
                user = new UserAdminVo();
                // 数据赋值
                BeanUtils.copyProperties(dUserExt, user);
                user.setLastLoginTime(TimeHelper.getTimestamp(dUserExt.getLastLoginTime()));
                user.setCreatedTime(TimeHelper.getTimestamp(dUserExt.getCreatedTime()));
                // 添加数据
                userList.add(user);
            }
        }
        // 赋值数据
        userAdminPage.setTotalCount(totalCount);
        userAdminPage.setList(userList);
        // 返回数据
        return userAdminPage;
    }

    /**
     * 修改用户
     *
     * @param myId 我的标识
     * @throws WayzException 云歌广告平台异常
     */
    @Override
    public void modifyUser(Long myId, UserAdminDto userAdminDto) throws WayzException {
        // 修改mysql数据库信息
        DUserAdmin dUserAdminModify = this.updateUser(userAdminDto);
        // 缓存用户
        this.updateCacheUser(dUserAdminModify);
    }

    /**
     * 修改msyql数据库用户信息
     * @return
     */
    private DUserAdmin updateUser(UserAdminDto userAdminDto) throws WayzException {

        UserAdminVo userAdminVo = new UserAdminVo();
        // 检查用户
        DUserAdmin dUserAdmin = dUserAdminDAO.get(userAdminDto.getId());
        if (dUserAdmin == null) {
            throw new WayzException("用户不存在!");
        }
        // 检查用户电话
        if (dUserAdminDAO.existsPhone(userAdminDto.getPhone(), userAdminDto.getId())) {
            throw new WayzException("手机号已存在!");
        }
        // 修改用户
        DUserAdmin dUserAdminModify = new DUserAdmin();
        dUserAdminModify.setId(userAdminDto.getId());
        dUserAdminModify.setName(userAdminDto.getName());
        dUserAdminModify.setPhone(userAdminDto.getPhone());
        dUserAdminModify.setEmail(userAdminDto.getEmail());
        dUserAdminDAO.modify(dUserAdminModify);

        //BeanUtils.copyProperties(dUserAdminModify, userAdminVo);

        return dUserAdminModify;
    }

    /**
     * 修改缓存中用户信息
     *
     * @param dUserAdminModify
     */
    private void updateCacheUser(DUserAdmin dUserAdminModify) throws WayzException {
        RUserAdmin rUserAdmin = new RUserAdmin();
        BeanUtils.copyProperties(dUserAdminModify, rUserAdmin);
        String key = RUserAdmin.getKey(dUserAdminModify.getId());
        redisUtils.hPutBeanAsHash(key, rUserAdmin);
    }

    /**
     * 修改用户的 启用/禁用 状态
     *
     * @param myId
     * @return
     * @throws WayzException
     */
    @Override
    public void updateUserStatus(Long myId, UserAdminDto userAdminDto) throws WayzException {
        dUserAdminDAO.updateUserStatus(userAdminDto.getId(), userAdminDto.getStatus());
        RUserAdmin rUserAdmin = new RUserAdmin();
        rUserAdmin.setStatus(userAdminDto.getStatus());
        String key = RUserAdmin.getKey(userAdminDto.getId());
        redisUtils.hPutBeanAsHash(key, rUserAdmin);
    }

    /**
     * 修改密码
     *
     * @param myId 我的标识
     * @throws WayzException 云歌广告平台异常
     */
    @Override
    public void modifyPassword(Long myId, UserAdminDto userAdminDto) throws WayzException {
        // 检查用户
        DUserAdmin dUserAdmin = dUserAdminDAO.get(myId);
        if (dUserAdmin == null) {
            throw new WayzException("用户不存在!");
        }
        if (userAdminDto.getOldPassword() == null || !userAdminDto.getOldPassword().equalsIgnoreCase(dUserAdmin.getPassword())) {
            throw new WayzException("原始密码错误!");
        }
        dUserAdminDAO.modifyPassword(myId, userAdminDto.getNewPassword());
    }

    /**
     * 删除用户
     *
     * @param myId 我的标识
     * @param id 用户标识
     * @throws WayzException 云歌广告平台异常
     */
    @Override
    public void deleteUser(Long myId, Long id) throws WayzException {
        if (id.equals(myId)) {
            throw new WayzException("不能删除自己!");
        }
        dUserAdminDAO.deleteUser(id);

        // 删除用户缓存
        redisUtils.delete(RUserAdmin.getKey(id));
    }

    /**
     * 统计指定角色的用户数量
     *
     * @param roleId
     * @return
     */
    @Override
    public Integer countUserByRoleId(Long roleId) {
        return dUserAdminDAO.countUserByRoleId(roleId);
    }
}
